﻿//Copyright 2011 - Jonathan Allen

using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Globalization;
using System.Linq;
using Granite.Eventing;

namespace Granite.Collections
{

    ///// <summary>
    ///// Helper methods for creating observing collections
    ///// </summary>
    //[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")]
    //public static class ObservingCollection
    //{
    //    /// <summary>
    //    /// This creates a ReadOnlyObservableCollection that is kept in sync with a parent collection of a different type. 
    //    /// </summary>
    //    /// <typeparam name="TSource">Type of item stored in the source collection</typeparam>
    //    /// <typeparam name="TTarget">Type of item stored in the target collection</typeparam>
    //    /// <param name="source">Source collection to be watched</param>
    //    /// <param name="convert">function that converts items in the source into items for the target</param>
    //    /// <returns>Target collection</returns>
    //    public static ObservingCollection<TTarget> ObserveWithConversion<TSource, TTarget>(this ObservableCollection<TSource> source, Func<TSource, TTarget> convert)
    //    {
    //        if (source == null)
    //            throw new ArgumentNullException("source", "source is null.");
    //        if (convert == null)
    //            throw new ArgumentNullException("convert", "convert is null.");

    //        var translator = new ObservingCollection<TTarget>.Translator<TSource>(source, convert);
    //        return new ObservingCollection<TTarget>(translator);
    //    }

    //    /// <summary>
    //    /// Returns an empty ObservingCollection.
    //    /// </summary>
    //    /// <typeparam name="TTarget"></typeparam>
    //    /// <returns></returns>
    //    public static ObservingCollection<TTarget> Empty<TTarget>()
    //    {
    //        return new ObservingCollection<TTarget>();
    //    }
    //}


    ///// <summary>
    ///// This represents a read-only collection that kept in sync with a source collection of a different type
    ///// </summary>
    ///// <typeparam name="TTarget">Type of item to be stored in the target collection</typeparam>
    //public sealed class ObservingCollection<TTarget> : WeakReadOnlyObservableCollection<TTarget>
    //{

    //    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
    //    readonly Translator m_Translator; //This is needed to prevent m_Translator from being garbage collected
    //    internal ObservingCollection(Translator translator)
    //        : base(translator.Target)
    //    {
    //        m_Translator = translator;
    //    }

    //    internal ObservingCollection()
    //        : base(new ObservableCollection<TTarget>()) { }

    //    internal abstract class Translator
    //    {
    //        readonly ObservableCollection<TTarget> m_Target = new ObservableCollection<TTarget>();

    //        public ObservableCollection<TTarget> Target
    //        {
    //            get { return m_Target; }
    //        }

    //    }

    //    internal sealed class Translator<TSource> : Translator
    //    {

    //        ObservableCollection<TSource> m_Source;
    //        readonly Func<TSource, TTarget> m_Translation;
    //        readonly CollectionChangedListener m_SourceCollectionChanged;

    //        public Translator(ObservableCollection<TSource> source, Func<TSource, TTarget> translation)
    //        {
    //            m_Translation = translation;
    //            m_Source = source;
    //            m_SourceCollectionChanged = new CollectionChangedListener(SourceCollectionChanged);
    //            WeakEventHandler.AddHandler(m_Source, m_SourceCollectionChanged);

    //            foreach (var item in m_Source)
    //            {
    //                Target.Add(m_Translation(item));
    //            }

    //        }

    //        void SourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    //        {
    //            switch (e.Action)
    //            {
    //                case NotifyCollectionChangedAction.Add:

    //                    var newList = (from i in e.NewItems.Cast<TSource>() select m_Translation(i)).ToList();
    //                    Target.InsertRange(e.NewStartingIndex, newList);

    //                    break;

    //                case NotifyCollectionChangedAction.Remove:

    //                    Target.RemoveRange(e.OldStartingIndex, e.OldItems.Count);

    //                    break;

    //                case NotifyCollectionChangedAction.Reset:

    //                    Target.Clear();

    //                    foreach (var item in m_Source)
    //                        Target.Add(m_Translation(item));

    //                    break;

    //                case NotifyCollectionChangedAction.Replace:

    //                    var newList2 = (from i in e.NewItems.Cast<TSource>() select m_Translation(i)).ToList();
    //                    for (var i = 0; i < newList2.Count; i++)
    //                    {
    //                        Target[e.NewStartingIndex + i] = newList2[i];
    //                    }

    //                    break;

    //                default:
    //                    //TODO - Handle the other cases for e.Action
    //                    throw new NotImplementedException(string.Format(CultureInfo.InvariantCulture, "Action type {0} is not supported.", e.Action));
    //            }
    //        }
    //    }
    //}

}

